package com.lingjtx.common.thread.config;


import com.lingjtx.common.thread.commom.ThreadPoolRefreshEvent;
import com.lingjtx.common.thread.core.PoolNameConst;
import com.lingjtx.common.thread.core.ThreadPoolBuilder;
import com.lingjtx.common.thread.core.ThreadPoolManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationListener;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;

@Configuration
@EnableAsync
public class ThreadPoolAutoConfig implements AsyncConfigurer,
        ApplicationContextAware,
        Ordered,
        ApplicationListener<ThreadPoolRefreshEvent> {

    private static final Logger log = LoggerFactory.getLogger(ThreadPoolAutoConfig.class);

    private final ThreadPoolManager threadPoolManager;
    private ConfigurableApplicationContext context;

    public ThreadPoolAutoConfig(ThreadPoolManager threadPoolManager) {
        this.threadPoolManager = threadPoolManager;
    }

    @Override
    public Executor getAsyncExecutor() {
        return threadPoolManager.getOrCreate(PoolNameConst.POOL_DEFAULT);
    }

    public void refreshExecutor(String name, ExecutorConfig.PoolConfig config) {
        // 1. 构建共享 ThreadPoolExecutor
        ThreadPoolExecutor executor = new ThreadPoolBuilder()
                .corePoolSize(config.getCorePoolSize())
                .maxPoolSize(config.getMaxPoolSize())
                .queueCapacity(config.getQueueCapacity())
                .keepAliveSeconds(config.getKeepAliveSeconds())
                .build(name);

        // 2. 注册到底层 threadPoolManager
        threadPoolManager.registerExecutor(name, executor);

        // 3. 构建共享底层线程池的 Spring TaskExecutor
        ThreadPoolTaskExecutor springExecutor = ThreadPoolBuilder.buildSpringExecutor(name, executor, config);
        springExecutor.initialize();

        // 4. 替换注册为 Spring Bean，供 @Async("xxx") 使用
        registerExecutorBean(name, springExecutor);
    }

    private void registerExecutorBean(String name, ThreadPoolTaskExecutor executor) {
        ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
        if (beanFactory.containsSingleton(name)) {
            beanFactory.destroyBean(name); // 先销毁旧 Bean
        }
        beanFactory.registerSingleton(name, executor);
    }

    @Override
    public void onApplicationEvent(ThreadPoolRefreshEvent event) {
        refreshExecutor(event.getName(), event.getConfig());
        log.info("底层线程池和 Spring Bean 线程池 [{}] 参数已热更新", event.getName());
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.context = (ConfigurableApplicationContext) applicationContext;
    }

    @Override
    public int getOrder() {
        return 4;
    }
}
